package rpc

import (
	"bigdevops/src/cache"
	"bigdevops/src/common"
	"bigdevops/src/config"
	"bigdevops/src/models"
	"bigdevops/src/pbms"
	"context"
	"go.uber.org/zap"
)

type JobExecServer struct {
	pbms.JobExecServer
	sc        *config.ServerConfig
	taskCache *cache.TaskCache
}

func (s *JobExecServer) TaskReport(ctx context.Context, in *pbms.TaskReportRequest) (resp *pbms.TaskReportResponse, err error) {

	s.sc.Logger.Info("收到任务执行结果上报的请求",
		zap.String("详情", in.String()),
		zap.String("ip", in.GetIp()),
		zap.String("hostname", in.GetHostname()),
	)

	// 需要做2件事
	// 01 结果信息的落库
	// 02 看看有没有新的任务需要下发给这个机器的

	resp = &pbms.TaskReportResponse{}

	for _, result := range in.GetResults() {
		result := result
		s.sc.Logger.Info("收到任务执行结果上报的请求，打印每个任务的结果",
			zap.String("ip", in.GetIp()),
			zap.String("hostname", in.GetHostname()),
			zap.Any("任务id", result.Id),
			zap.Any("任务状态", result.Status),
			zap.Any("任务stdout", result.StdOut),
			zap.Any("任务stderr", result.StdErr),
		)

		// 构造这个结果update即可
		dbResult, err := models.GetJobResultByJobIdAndHostIp(int(result.Id), in.GetIp())
		if err != nil {
			s.sc.Logger.Error("收到任务执行结果上报的请求，更新结果前查询记录错误",
				zap.Error(err),
				zap.String("ip", in.GetIp()),
				zap.String("hostname", in.GetHostname()),
				zap.Any("任务id", result.Id),
				zap.Any("任务状态", result.Status),
				zap.Any("任务stdout", result.StdOut),
				zap.Any("任务stderr", result.StdErr),
			)
			continue
		}

		dbResult.Status = result.Status
		dbResult.Stdout = result.StdOut
		dbResult.Stderr = result.StdErr

		err = dbResult.UpdateOne()
		if err != nil {
			s.sc.Logger.Error("收到任务执行结果上报的请求，更新结果错误",
				zap.Error(err),
				zap.String("ip", in.GetIp()),
				zap.String("hostname", in.GetHostname()),
				zap.Any("任务id", result.Id),
				zap.Any("任务状态", result.Status),
				zap.Any("任务stdout", result.StdOut),
				zap.Any("任务stderr", result.StdErr),
			)
			continue
		}
		resp.ReceivedTaskIds = append(resp.ReceivedTaskIds, int32(result.Id))
		dbResult.JudgeByOnErrorStrategy()
	}

	// 如何取到你需要的任务
	finalTasks := []*pbms.TaskAssignOne{}
	// 这个机器要下发的任务列表
	// 思考如果在这里renew 那么多个节点 频繁操作，
	tasks := s.taskCache.GetTasksByIp(in.GetIp())
	// 遍历task转化为 proto
	for _, task := range tasks {
		task := task

		pt := &pbms.TaskAssignOne{
			Id:                 int32(task.ID),
			ExecTimeoutSeconds: int32(task.ExecTimeoutSeconds),
			ScriptContent:      task.ScriptContent,
			Account:            task.Account,
			Args:               task.Args,
			Action:             task.Action,
		}
		finalTasks = append(finalTasks, pt)

		// 新建结果表 ，status设置为running，目的是下次cache中就没有这个任务了
		dbJobResult := &models.JobResult{
			JobId:    task.ID,
			Status:   common.JOB_STATUS_RUNNING,
			HostIp:   in.Ip,
			HostName: in.Hostname,
		}
		err = dbJobResult.GetOrCreate()
		if err != nil {
			s.sc.Logger.Error("grpc收到agent上报数据，下发新任务，初始化创建任务结果表错误",
				zap.String("ip", in.GetIp()),
				zap.String("hostname", in.GetHostname()),
				zap.Any("任务id", task.ID),
				zap.Error(err),
			)
		}

	}
	//tPing := &pbms.TaskAssignOne{
	//	Id:            5,
	//	ScriptContent: "ping baidu.com",
	//	Account:       "root",
	//	//Action:        common.AGENT_TASK_ACTION_START,
	//	Action:             common.AGENT_TASK_ACTION_KILL,
	//	ExecTimeoutSeconds: 100000,
	//}
	//tasks = append(tasks, tPing)
	resp.Tasks = finalTasks

	return

}
